package vengadores;

import java.io.IOException;
import java.util.Random;
import java.util.Vector;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.LayerManager;
import javax.microedition.lcdui.game.Sprite;

/**
 *Es la clase que maneja los eventos específicos del modo de Plataforma del juego. En esta clase se manejan los golpes, la interacción del jugador con el juego, del heroe con el enemigo
 * y de los eventos que surjan de estas interacciones.
 * @author Felipe Donato Arrazola Gómez
 * @author Jorge de Jesús Tinoco Huesca
 * @author Arturo Ayala Tello
 */
public class AdminPlataforma extends LayerManager{

    /**
     * Es el heroe que jugará la partida en el juego
     */
    protected Heroe heroe;
    /**
     * Es el conjunto de enemigos que atacarán al heroe
     */
    protected Vector enemigos;
    /**
     * Mapa que se dibujará a lo largo del modo de Plataforma
     */
    protected MapaPlataforma mapa;
    /**
     * Fondo del modo de Plataforma
     */
    protected Fondo fondo,cielo;
    private Juego juego; // juego al que pertenece el administrador
    /**
     * variable que almacena el puntaje obtenido durante el modo Plataforma
     */
    protected int puntaje=0;
    private int ANCHO, ALTO; //enteros que representan las medidas de la pantalla
    private int sexoPersonaje;//entero que guarda el genero del heroe
    private Random random;//objeto para generar números aleatorios
    private int pasosEnemigo;//rango de pasos para el movimiento del enemigo
    private int rango; //el rango que tiene que cubrir para el desplazamiento del enemigo
    private int golpesMaximos;//variable que aloja el número de golpes que soporta el enemigo
    private int desplazamiento; // es el desplazamiento del mapa durante el juego
    private int nivel;// es el nivel del modo de Plataforma
    private int tamanoEnemigos;//tamaño del conjunto de enemigos
    private Sprite tequila;//Sprite de un objeto que sube el atributo de vidas del heroe
    private Sprite sabripobres;// Sprite de un objeto que sube el atributo de sangre del heroe

    /**
     * Constructor de la clase del administrador del modo Plataforma. Genera un LayerManager que contiene
     * todos los elementos de este modo de juego
     * @param jgo es el juego al que pertenece el administrador
     * @param ancho es el ancho de la pantalla
     * @param alto es el alto de la pantalla
     * @param sexo es el genero del heroe
     * @param nivel es el nivel que se va a jugar
     */
    public AdminPlataforma(Juego jgo, int ancho, int alto, int sexo, int nivel){
       this.nivel = nivel;
        this.sexoPersonaje = sexo;
        juego = jgo;
        enemigos = new Vector(8);
        random = new Random();
        rango = 100;
        ANCHO = ancho;
        ALTO = alto;
        if(sexoPersonaje == 0){
            golpesMaximos = 1;
        }else if(sexoPersonaje == 1){
            golpesMaximos = 2;
        }
        try {
            Image imagen = null;
            tequila = new Sprite(Image.createImage("/rancho.png"), 50, 50);
            sabripobres = new Sprite(Image.createImage("/Sabritones.png"),45,45);
            switch(this.nivel){
                case 1:
                    imagen = Image.createImage("/MapaJuarez.png");
                    cielo = new Fondo("/Cielo.png");
                    mapa = new MapaPlataforma(121, 10, imagen, 32, 32, 1);
                    fondo = new Fondo("/JuarezBack.png");
                    for(int i=0; i<3; i++){
                        enemigos.addElement(new Enemigo(Enemigo.PLATAFORMA, 1));
                    }
                    for(int i=3;i<6;i++){
                        enemigos.addElement(new Enemigo(Enemigo.OBSTACULO, 1));
                    }
                    for(int i=0; i<enemigos.size(); i++){
                        Enemigo e = (Enemigo) enemigos.elementAt(i);
                        e.setPosition(random.nextInt(mapa.getWidth()), 0);
                        for(;;){
                            e.move(0, 1);
                            if(e.collidesWith(mapa, true)){
                                   break;
                            }else if(e.getY()>ALTO){
                                e.setPosition(random.nextInt(mapa.getWidth()), 0);
                            }
                        }
                        this.append(e);
                    }
                    this.append(sabripobres);
                    sabripobres.setPosition(random.nextInt(mapa.getWidth()), 70);
                    break;
                case 2:
                    imagen = Image.createImage("/MapaAcapulco.png");
                    cielo = new Fondo("/CieloAcapulco.png");
                    mapa = new MapaPlataforma(140,10,imagen, 32, 32 , 2);
                    fondo = new Fondo("/AcapulcoPlataforma.png");
                    for(int i=0; i<4; i++){
                        enemigos.addElement(new Enemigo(Enemigo.PLATAFORMA, 2));
                        Enemigo e = (Enemigo) enemigos.elementAt(i);
                        e.setPosition(random.nextInt(mapa.getWidth()), 0);
                        for(;;){
                            e.move(0, 1);
                            if(e.collidesWith(mapa, true)){
                                   break;
                            }else if(e.getY()>ALTO){
                                e.setPosition(random.nextInt(mapa.getWidth()), 0);
                            }
                        }
                        this.append(e);
                    }
                    for(int i=4;i<8;i++){
                        enemigos.addElement(new Enemigo(Enemigo.OBSTACULO_MOVIL, 2));
                        Enemigo e = (Enemigo) enemigos.elementAt(i);
                        e.setPosition(random.nextInt(mapa.getWidth()), 0);
                        this.append(e);
                    }
                    this.append(tequila);
                    tequila.setPosition((mapa.getWidth()/2)+random.nextInt(mapa.getWidth()/2), 70);
                    this.append(sabripobres);
                    sabripobres.setPosition(random.nextInt(mapa.getWidth()), 70);
                    break;
                case 3:
                    cielo = new Fondo("/MexicoNubes.png");
                    imagen = Image.createImage("/MapaMexico.png");
                    mapa = new MapaPlataforma(130,10,imagen, 32, 32 , 3);
                    this.append(mapa);
                    fondo = new Fondo("/MexicoFondo.png");
                    for(int i=0; i<4; i++){
                        enemigos.addElement(new Enemigo(Enemigo.PLATAFORMA, 2));
                        Enemigo e = (Enemigo) enemigos.elementAt(i);
                        e.setPosition(random.nextInt(mapa.getWidth()), 0);
                        for(;;){
                            e.move(0, 1);
                            if(e.collidesWith(mapa, true)){
                                   break;
                            }else if(e.getY()>ALTO){
                                e.setPosition(random.nextInt(mapa.getWidth()), 0);
                            }
                        }
                        this.append(e);
                    }
                    for(int i=4;i<8;i++){
                        enemigos.addElement(new Enemigo(Enemigo.OBSTACULO_MOVIL, 3));
                        Enemigo e = (Enemigo) enemigos.elementAt(i);
                        e.setPosition(random.nextInt(mapa.getWidth()), 0);
                        this.append(e);
                    }
                    this.append(tequila);
                    tequila.setPosition((mapa.getWidth()/2)+random.nextInt(mapa.getWidth()/2), 70);
                    this.append(sabripobres);
                    sabripobres.setPosition(random.nextInt(mapa.getWidth()), 70);
                    break;
            }
            imagen = null;
            this.append(mapa);

            tamanoEnemigos = enemigos.size();
            heroe = new Heroe(sexo);
            for(;;){
                heroe.move(0, 1);
                if(heroe.collidesWith(mapa, true)){
                    heroe.move(0, -1);
                    break;
                }
            }
            this.append(heroe);
            desplazamiento = 0;
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    /**
     * Método que dibuja la plataforma en un entorno gráfico
     * @param g es el entorno gráfico donde se dibujará el administrador de la Plataforma
     */

    public void dibujar(Graphics g){
        int desp=0;
        cielo.mover(-1);
        if ( heroe.getX()>mapa.getWidth()-ANCHO/2 ) { // ultima mitad
            desp = mapa.getWidth()-ANCHO;
        }
        else if ( heroe.getX() > ANCHO/2 ) {
            desp = heroe.getX()-ANCHO/2;
            if (desp > desplazamiento){
                fondo.mover(-1);
            }else if(desp < desplazamiento){
                fondo.mover(1);
            }
        }
        desplazamiento = desp;
        cielo.dibujar(g);
        fondo.dibujar(g);
        setViewWindow(desplazamiento, 0, ANCHO, ALTO);
        paint(g, 0, 0);
        movItems();
    }

    /**
     * Método que elimina todas las referencias de la clase
     */
    public void terminar(){
        juego = null;
        random = null;
        heroe = null;
        for(int i=0;i<enemigos.size();i++){
            Enemigo e = (Enemigo)enemigos.elementAt(i);
            e = null;
        }
        enemigos = null;
        mapa = null;
        fondo.terminar();
        fondo = null;
        cielo.terminar();
        cielo = null;
        enemigos = null;
        sabripobres = null;
        tequila = null;
    }

    /**
     * Método que se encarga de desplazar a los enemigos. Este método utiliza rangos y pasos para controlar de forma
     * más eficaz el rango de ataque del enemigo, si el heroe se acerca mucho al enemigo, lo golpea, y si la posición en x
     * del heroe es mayor a la del enemigo, éste lo perseguirá
     */
    public void movimientoEnemigo(){
        for(int i=0; i<tamanoEnemigos; i++){
            Enemigo enemigo = (Enemigo) enemigos.elementAt(i);
            int tipoEnemigo = enemigo.getTipo();
            if(tipoEnemigo == Enemigo.PLATAFORMA){
                movEnemigoPlataforma(enemigo);
            }else if(tipoEnemigo == Enemigo.OBSTACULO){
                movObstaculo(enemigo);
            }else if(tipoEnemigo == Enemigo.OBSTACULO_MOVIL){
                movObstaculoMovil(enemigo);
            }
        }
    }

    //Método que se encarga de mover los obstaculos alrededor del mapa
    private void movObstaculoMovil(Enemigo enemigo) {
        int x = enemigo.getX();
        int y = enemigo.getY();
        int alturaEnemigo = enemigo.getHeight();
        if (enemigo.collidesWith(mapa, true) || enemigo.estaRompiendo) {
            enemigo.romperObstaculo();
            enemigo.setPosition(x, y);
            enemigo.nextFrame();
            if(enemigo.getFrame() == Enemigo.ULTROTO){
                enemigo.setPosition(random.nextInt(3200), -alturaEnemigo);
            }
        }else if (enemigo.collidesWith(heroe, true) && !heroe.haSidoGolpeado) {
            if (x > heroe.getX()) {
                heroe.move(-5, 0);
                if (heroe.collidesWith(mapa, true))
                    heroe.move(5, 0);
            } else {
                heroe.move(5, 0);
                if (heroe.collidesWith(mapa, true))
                    heroe.move(-5,0);
            }
            heroe.golpeado();
            if (juego.getMidlet().deseaVibracion())
                Display.getDisplay(juego.getMidlet()).vibrate(500);
            Heroe.SANGRE--;
        }else{
            enemigo.setFrameSequence(null);
            enemigo.setFrame(0);
            enemigo.move(0, 20);
        }
    }

    //Método que posiciona los objetos de ayuda a lo largo del mapa
    private void movItems(){
        tequila.nextFrame();
        sabripobres.nextFrame();
        if(heroe.collidesWith(tequila, true)){
            tequila.setVisible(false);
            Heroe.VIDAS++;
        }
        if(heroe.collidesWith(sabripobres, true)){
            sabripobres.setVisible(false);
            Heroe.SANGRE+=2;
        }
    }

    //Método que se encarga de posicionar los obstaculos no móviles en el administrador
    private void movObstaculo(Enemigo enemigo) {
        int x = enemigo.getX();
        if (enemigo.collidesWith(heroe, true) && !heroe.estaBrincando && !heroe.haSidoGolpeado) {
            if (x > heroe.getX()) {
                heroe.move(-5, 0);
                if (heroe.collidesWith(mapa, true))
                    heroe.move(5, 0);
            } else {
                heroe.move(5, 0);
                if(heroe.collidesWith(mapa, true))
                    heroe.move(-5, 0);
            }
            heroe.golpeado();
            if (juego.getMidlet().deseaVibracion())
                Display.getDisplay(juego.getMidlet()).vibrate(500);
            Heroe.SANGRE--;
        }
    }

    //Método que complementa a MovEnemigo
    private void movEnemigoPlataforma(Enemigo enemigo) {
        int x = enemigo.getX();
        int y = enemigo.getY();
        enemigo.move(0,5);
        if(enemigo.collidesWith(mapa, true)){
            enemigo.move(0, -5);
            if(enemigo.vecesGolpeado >= golpesMaximos || enemigo.estaMuriendo){
                //CUANDO MATES A UN ENEMIGO
                enemigo.morir();
                if(enemigo.getFrame() == Enemigo.ULTMUERTO){
                    puntaje+=50;
                    enemigo.setPosition(random.nextInt(3200), 0);
                    for(;;){
                        enemigo.move(0, 1);
                        if(enemigo.collidesWith(mapa, true)){
                                break;
                        }
                    }
                }
            }else if(enemigo.haSidoGolpeado){
                //CUANDO EL ENEMIGO HAYA SIDO GOLPEADO
                enemigo.golpeado();
            }else {
                //MOVIMIENTO NORMAL DEL ENEMIGO
                if ((x - heroe.getX()) > 50) {
                    if (pasosEnemigo < rango / 2) {
                        enemigo.correr(true);
                    } else if (pasosEnemigo == rango / 2) {
                        enemigo.setTransform(Enemigo.TRANS_MIRROR);
                        enemigo.setPosition(x, y);
                    } else if (pasosEnemigo == rango) {
                        pasosEnemigo = 0;
                        enemigo.setTransform(Enemigo.TRANS_NONE);
                        enemigo.setPosition(x, y);
                    } else if (pasosEnemigo > rango / 2) {
                        enemigo.correr(false);
                    }
                    pasosEnemigo++;
                } else if (((x - heroe.getX()) < 30 && (x - heroe.getX()) > -60) && !enemigo.haSidoGolpeado
                        && !heroe.estaCayendo && !heroe.estaMuriendo) {
                    //AQUI ESTA PARA QUE EL ENEMIGO GOLPEE
                    if(x<heroe.getX()){
                        enemigo.setTransform(Sprite.TRANS_NONE);
                        enemigo.setPosition(x, y);
                    }else{
                        enemigo.setTransform(Sprite.TRANS_MIRROR);
                        enemigo.setPosition(x, y);
                    }
                    enemigo.golpear();
                    if(enemigo.collidesWith(heroe, true) && !heroe.estaBrincando && !heroe.estaAgachado){
                        if(x>heroe.getX()){
                            heroe.move(-5, 0);
                            if(heroe.collidesWith(mapa, true))
                                heroe.move(5, 0);
                        }
                        else{
                            heroe.move(5, 0);
                            if (heroe.collidesWith(mapa, true))
                                heroe.move(-5, 0);
                        }
                        heroe.golpeado();
                        if (juego.getMidlet().deseaVibracion())
                            Display.getDisplay(juego.getMidlet()).vibrate(500);
                        Heroe.SANGRE--;
                    }
                } else {
                    //CUANDO TE ACERQUES Y TE SIGA
                    if (x > heroe.getX()) {
                        enemigo.correr(false);
                    } else {
                        enemigo.correr(true);
                    }
                }
                checarGolpe();
            }
            enemigo.nextFrame();
        }
   }

    //Método que comprueba si el enemigo golpea al heroe o viceversa
    private void checarGolpe(){
        for(int i=0; i<tamanoEnemigos; i++){
            Enemigo enemigo = (Enemigo) enemigos.elementAt(i);
            int x = enemigo.getX();
            int y = enemigo.getY();
            if((heroe.collidesWith(enemigo, true)) && heroe.estaGolpeando){
                enemigo.golpeado();
                enemigo.vecesGolpeado++;
                if(x>heroe.getX()){
                    enemigo.setTransform(Sprite.TRANS_NONE);
                    enemigo.setPosition(x, y);
                    enemigo.move(10, 0);
                }else{
                    enemigo.setTransform(Sprite.TRANS_MIRROR);
                    enemigo.setPosition(x, y);
                    enemigo.move(-10, 0);
                }

            }
        }
    }
}
